#include "includes.h"

#include "DMA_UART.h"
#include  "queue.h"

#define	 	DMA_UART3_En		1
//#include "usart.h"
#include "usart3.h"


#if DMA_UART3_En
void DMA_UART3_INIT(void);
void USART3_DMA_WRITE(uint8_t *data,uint16_t size);

OS_EVENT * USART3_Send_Sem;
OS_EVENT * USART3_Recv_Sem;
#endif

#if DMA_UART3_En

void USART3_Create_Sem(void)
{	
#if OS_CRITICAL_METHOD == 3u
    OS_CPU_SR cpu_sr=0u;
#endif
    OS_ENTER_CRITICAL();  //进入临界区(关闭中断)
    USART3_Send_Sem = OSSemCreate(0);    
	USART3_Recv_Sem = OSSemCreate(0); 
    OS_EXIT_CRITICAL();  //退出临界区(开中断)
}

void usart3_init(u32 bound)
{  

	NVIC_InitTypeDef NVIC_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	// GPIOB时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE); //串口3时钟使能

 	USART_DeInit(USART3);  //复位串口3
		 //USART3_TX   PB10
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB10
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
	GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB10
   
    //USART3_RX	  PB11
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
	GPIO_Init(GPIOB, &GPIO_InitStructure);  //初始化PB11
	
	USART_InitStructure.USART_BaudRate = bound;//波特率一般设置为9600;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
  
	USART_Init(USART3, &USART_InitStructure); //初始化串口	3
  

	USART_Cmd(USART3, ENABLE);                    //使能串口 
	
	//使能接收中断
	USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启中断 
	USART_ITConfig(USART3, USART_IT_IDLE, ENABLE);
 

	
	//设置中断优先级
	NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
	
	#if DMA_UART3_En
	DMA_UART3_INIT();
	#endif
	//TIM4_Int_Init(99,7199);		//10ms中断
	//USART3_RX_STA=0;		//清零
	//TIM_Cmd(TIM4,DISABLE);			//关闭定时器7
	

}










//----DMA初始化
void DMA_UART3_INIT(void)
{
NVIC_InitTypeDef NVIC_InitStructure ;	
	
	DMA_UART_CONFIG(DMA1_Channel3, USART3,DMA_DIR_PeripheralSRC,USART_DMAReq_Rx,Queue_Frame_Usart3.DMA_UARTn_RX_Buf, DMA_RX3_LEN);
	DMA_SetCurrDataCounter(DMA1_Channel3,DMA_RX3_LEN);
    DMA_Cmd(DMA1_Channel3, ENABLE); 
	
	DMA_UART_CONFIG(DMA1_Channel2, USART3,DMA_DIR_PeripheralDST,USART_DMAReq_Tx,Queue_Frame_Usart3.DMA_UARTn_TX_Buf, DMA_TX3_LEN);

	DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE);  
	DMA_ITConfig(DMA1_Channel2, DMA_IT_TE, ENABLE);         

	
	NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn;   
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;   
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 7;   
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;   
    NVIC_Init(&NVIC_InitStructure); 
}	

//--UART2  dma 发送中断
void DMA1_Channel2_IRQHandler(void)
{
    if(DMA_GetITStatus(DMA1_IT_TC2) != RESET) 
	{
		//清除标志位
		DMA_ClearFlag(DMA1_FLAG_TC2);
		//关闭DMA
		DMA_Cmd(DMA1_Channel2,DISABLE);
		//打开发送完成中断,发送最后两个字节
		USART_ITConfig(USART3,USART_IT_TC,ENABLE);
	}
}
//--UART2  dma 接收中断
void DMA1_Channel3_IRQHandler(void)
{
	if((DMA_GetITStatus(DMA1_IT_TC3) != RESET) || (DMA_GetITStatus(DMA1_IT_TE3)) )
	{
		DMA_ClearITPendingBit(DMA1_IT_TC3);  
		DMA_ClearITPendingBit(DMA1_IT_TE3);  
		DMA_Cmd(DMA1_Channel3, DISABLE);         
		DMA1_Channel3->CNDTR = 512;              
		DMA_Cmd(DMA1_Channel3, ENABLE);  
	}			
} 

//--UART2  发送初始化
void USART3_TX_Init(void)
{
#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
		OS_CPU_SR  cpu_sr = 0u;
#endif	
	OS_ENTER_CRITICAL();
	USART3_Send_Sem->OSEventCnt = 0;
	OS_EXIT_CRITICAL();
}




/*********************************************************************
*							接口函数:向gsm模块发送数据
*参数:data:发送数据存放地址
*	  size:发送数据字节数
**********************************************************************/
UINT32	Flag_UART3_Tx__Busy = 0;	
void USART3_DMA_WRITE(uint8_t *data,uint16_t size)
{
    UINT8 err = 0;	
	UINT32 Busy;
#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
		OS_CPU_SR  cpu_sr = 0u;
#endif		
	while(1)
	{
		OS_ENTER_CRITICAL();
		Busy = Flag_UART3_Tx__Busy;
		OS_EXIT_CRITICAL();	
		if (Busy == 0)
			break;	
		OSTimeDly(2);
	}	
	OS_ENTER_CRITICAL();
	Flag_UART3_Tx__Busy = 1;
	OS_EXIT_CRITICAL();
	
	USART3_TX_Init();
	//复制数据
	memcpy(Queue_Frame_Usart3.DMA_UARTn_TX_Buf,data,size);
	//设置传输数据长度
	DMA_SetCurrDataCounter(DMA1_Channel2,size);
	//打开DMA,开始发送
 	DMA_Cmd(DMA1_Channel2,ENABLE);
	//等待空闲	
	OSSemPend(USART3_Send_Sem, 2000, &err); 
	
	OS_ENTER_CRITICAL();
	Flag_UART3_Tx__Busy = 0;
	OS_EXIT_CRITICAL();	
}

/**
AT命令的USART_OUT
**/
static void WriteByteToBuf(char *buf,INT32 *index, char data)
{
INT32	i = *index;
	if (i < 128)
	{		
		buf[i] = data;
		*index = i + 1;
	}
}
static char *itoa(int value, char *string, int radix)
{
    int     i, d;
    int     flag = 0;
    char    *ptr = string;
    if (radix != 10)
    {
        *ptr = 0;
        return string;
    }
    if (!value)
    {
        *ptr++ = 0x30;
        *ptr = 0;
        return string;
    }
    if (value < 0)
    {
        *ptr++ = '-';
        value *= -1;
    }
    for (i = 10000; i > 0; i /= 10)
    {
        d = value / i;
        if (d || flag)
        {
            *ptr++ = (char)(d + 0x30);
            value -= (d * i);
            flag = 1;
        }
    }
    *ptr = 0;
    return string;
}


void USART3_OUT(char *Data,...)
{ 
	const char *s;
    int d;
    char buf[16];
	char BUFFER[128];
	INT32	j = 0;
    va_list ap;
    va_start(ap, Data);

	while(*Data!=0)
	{	                       
		if(*Data==0x5c)
		{									  //'\'
			switch (*++Data)
			{
				case 'r':							          //???
					WriteByteToBuf(BUFFER,&j ,0x0d);	   

					Data++;
					break;
				case 'n':							          //???
					WriteByteToBuf(BUFFER,&j ,0x0a);	
					Data++;
					break;
				
				default:
					Data++;
				    break;
			}	 
		}
		else if(*Data=='%')
		{									  //
			switch (*++Data)
			{				
				case 's':										  //???
                	s = va_arg(ap, const char *);
                	for ( ; *s; s++) {
                    	WriteByteToBuf(BUFFER,&j , *s);
                	}
					Data++;
                	break;
            	case 'd':										  //???
                	d = va_arg(ap, int);
                	itoa(d, buf, 10);
                	for (s = buf; *s; s++) {
                    	WriteByteToBuf(BUFFER,&j, *s);
                	}
					Data++;
                	break;
				default:
					Data++;
				    break;
			}		 
		}
		else WriteByteToBuf(BUFFER,&j , *Data++);
	}
	USART3_DMA_WRITE((UINT8 *)BUFFER,j);
}

void USART3_Read_DMA2RxBuf(void)
{
uint16_t len;	
	len = DMA_RX3_LEN - DMA_GetCurrDataCounter(DMA1_Channel3);
	if (len == 0)
		return;
	if (Enqueue(&Queue_Frame_Usart3,Queue_Frame_Usart3.DMA_UARTn_RX_Buf,len) == 0)
	{
		OSSemPost(USART3_Recv_Sem);
		return;
	}
	else
	{
		return; 
	}	
}	




void USART3_CLEAR_RX(void)
{
#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
    OS_CPU_SR  cpu_sr = 0u;
#endif
	OS_ENTER_CRITICAL(); 	
	INIT_Queue_Frame(&Queue_Frame_Usart3);
	USART3_Recv_Sem->OSEventCnt = 0;
	OS_EXIT_CRITICAL(); 
}

void USART3_IRQHandler(void)
{
	OSIntEnter();	
	//发送完成中断处理
	if(USART_GetITStatus(USART3, USART_IT_TC) != RESET)
    {
		//关闭发送完成中断
		USART_ITConfig(USART3,USART_IT_TC,DISABLE);
		//发送完成
		OSSemPost(USART3_Send_Sem);
    } 
	
	
	//接收完成中断
	if(USART_GetITStatus(USART3, USART_IT_IDLE) != RESET)
    {
    	USART3->SR;
    	USART3->DR; //清USART_IT_IDLE标志
		USART_ClearITPendingBit(USART3,USART_IT_IDLE);
		//关闭DMA
    	DMA_Cmd(DMA1_Channel3,DISABLE);
		//清除标志位
		DMA_ClearFlag(DMA1_FLAG_GL3 | DMA1_FLAG_TC3 | DMA1_FLAG_TE3 | DMA1_FLAG_HT3);
		DMA_ClearFlag(DMA1_FLAG_TC3);
		
		USART3_Read_DMA2RxBuf();		
		//设置传输数据长度
		DMA_SetCurrDataCounter(DMA1_Channel3,DMA_RX3_LEN);
    	//打开DMA
		DMA_Cmd(DMA1_Channel3,ENABLE);
    } 
	OSIntExit();    	 					//触发任务切换软中断 											 
}

#endif

INT32 USART3_Read(UINT8 *BUF, UINT32 len, UINT32 timeout)
{
	INT32 tlen = 0;
    UINT8 err = 0;	
	OS_CPU_SR  cpu_sr = 0u;
			
	OSSemPend(USART3_Recv_Sem, timeout, &err); 
	if (err == OS_ERR_NONE)
	{
		//	memset(ProtoTxRx.BUF,0,20);
		OS_ENTER_CRITICAL();
		tlen = Dequeue(&Queue_Frame_Usart3,(uint8_t *)BUF, len);
		OS_EXIT_CRITICAL();		
	}	
	else
	{
		tlen = -1;
	}	
	return tlen;
}



INT32 USART3_Read_NoBlock(UINT8 *BUF, UINT32 len)
{
	INT32 tlen = 0;
	OS_CPU_SR  cpu_sr = 0u;
			
	if (OSSemAccept(USART3_Recv_Sem) > 0)
	{
		//	memset(ProtoTxRx.BUF,0,20);
		OS_ENTER_CRITICAL();
		tlen = Dequeue(&Queue_Frame_Usart3,(uint8_t *)BUF, len);
		OS_EXIT_CRITICAL();		
	}	
	else
	{
		tlen = -1;
	}	
	return tlen;
}

